﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using Might.Infrastructure.Annotations.Graphics;

namespace Might.GraphicsEditor.GraphicsObjects {
    /// <summary>
    /// Class representation for simple line
    /// </summary>
    public class LeafLine : GraphicsComponent {
        internal List<Point> points;
        internal Path Path { get; set; }

        /// <summary>
        /// Color of the stroke
        /// </summary>
        public Brush Stroke {
            get { return Path.Stroke; }
            set { Path.Stroke = value; }
        }

        /// <summary>
        /// Thickness of the outline
        /// </summary>
        public double StrokeThickness {
            get { return Path.StrokeThickness; }
            set { Path.StrokeThickness = value; }
        }

        /// <summary>
        /// Public constructor for simple line
        /// </summary>
        /// <param name="ga">Graphic annotation for this object</param>
        public LeafLine(IGraphicsItem ga) {
            this.ga = ga;
            Path = new Path {
                StrokeLineJoin = PenLineJoin.Bevel,
                Stretch = Stretch.Fill
            };
            Content = Path;

            UpdateShape();

            this.ga.Changed += GaGraphicsPrimitiveChanged;
        }

        /// <summary>
        /// Shows current changes in layout.
        /// </summary>
        protected override void UpdateShape() {
            base.UpdateShape();
            IGraphicsLine g = ga as IGraphicsLine;
            if (g == null) {
                throw new NullReferenceException("Updating Null anotation");
            }
            if (Stroke != g.Stroke) {
                Stroke = g.Stroke;
            }
            if (StrokeThickness != g.Thickness) {
                StrokeThickness = g.Thickness;
            }
            points = g.Points;
            Path.Data = GetLineGeometry();
            Path.StrokeStartLineCap = g.StartCap;
            Path.StrokeEndLineCap = g.EndCap;
        }

        /// <summary>
        /// Convert array of points to geometry.
        /// </summary>
        private Geometry GetLineGeometry() {
            PathSegmentCollection segments = new PathSegmentCollection();
            Point startpoint;

            if (points.Count <= 1) return new PathGeometry();

            if (((IGraphicsLine) ga).Smooth && points.Count >= 3) {
                startpoint = new Point((points[0].X + points[1].X)/2, (points[0].Y + points[1].Y)/2);

                for (int i = 2; i < points.Count; i++) {
                    segments.Add(
                        new QuadraticBezierSegment {
                            Point2 = new Point((points[i - 1].X + points[i].X)/2, (points[i - 1].Y + points[i].Y)/2),
                            Point1 = points[i - 1]
                        });
                }
            } else {
                startpoint = points[0];

                for (int i = 1; i < points.Count; i++) {
                    segments.Add(new LineSegment {Point = points[i]});
                }
            }

            PathGeometry data = new PathGeometry {
                Figures = new PathFigureCollection {
                    new PathFigure {
                        IsClosed = false,
                        StartPoint = startpoint,
                        Segments = segments
                    }
                }
            };

            return data;
        }
    }
}
